// api/workspaces/workspace.controller.js
import * as fs from "fs";
import * as path from "path";
import _ from "lodash";
import WorkspaceService from "./workspace.service.js";
import WorkspaceSerializer from "./workspace.serializer.js";
import WorkspaceValidator from "./workspace.validator.js";

class Controller {
  async index(req, res) {
    const workspaces = await WorkspaceService.find({ 
      $or: [
        { userId: req.user._id }, 
        { "teams._id": { $in: req.user.teams?.map(team => team._id) || [] } },
        { "members.userId": req.user._id }  // Add this to support the new members field
      ],
      accountId: req.user.accountId
    });
    return res.json(WorkspaceSerializer.index(workspaces));
  }

  async byId(req, res) {
    const workspace = await WorkspaceService.findByIdAndUser(
      req.params.id,
      req.user._id,
      req.user.accountId
    );
    
    if (workspace) {
      // Update last accessed timestamp
      await WorkspaceService.update(
        workspace._id,
        req.user._id,
        req.user.accountId,
        { lastAccessed: new Date() }
      );
      
      return res.json(WorkspaceSerializer.show(workspace));
    } else {
      return res.status(404).json({
        success: false,
        message: "Workspace not found."
      });
    }
  }

  async create(req, res) {
    const errors = await WorkspaceValidator.onCreate(req.body);
    if (errors) {
      return res.status(422).json({
        success: false,
        errors: errors.details,
      });
    }
    
    // Add the current user to the members array if not already included
    const members = req.body.members || [];
    const userAlreadyMember = members.some(member => 
      member.userId && member.userId.toString() === req.user._id.toString()
    );
    
    if (!userAlreadyMember) {
      members.push({
        userId: req.user._id,
        name: req.user.name,
        email: req.user.email,
        role: "admin",
        joinedAt: new Date()
      });
    }
    
    const workspaceData = _.pick(req.body, [
      "name",
      "slug",
      "description",
      "timezone",
      "filePath",
      "fileType",
      "fileSize",
      "metadata",
      "isPublic",
      "teams",
      "contacts",
      "projects",
      "meetings",
      "notes",
      "tasks",
      "mysqlHost",
      "mysqlPort",
      "mysqlUser",
      "mysqlPassword",
      "mysqlDatabase",
      "mysqlTable",
      "mysqlConnectionType"
    ]);
    
    // Add the members array
    workspaceData.members = members;
    // Set the ownerId to the current user
    workspaceData.ownerId = req.user._id;
    
    const workspace = await WorkspaceService.create(
      workspaceData,
      req.user._id,
      req.user.accountId
    );
    
    if (workspace) {
      return res.json(WorkspaceSerializer.show(workspace));
    } else {
      return res.status(422).json({
        success: false,
        message: "Failed to create workspace."
      });
    }
  }

  async update(req, res) {
    const errors = await WorkspaceValidator.onUpdate(req.body);
    if (errors) {
      return res.status(422).json({
        success: false,
        errors: errors.details,
      });
    }
    
    const workspaceData = _.pick(req.body, [
      "name",
      "slug",
      "description",
      "timezone",
      "filePath",
      "fileType",
      "fileSize",
      "metadata",
      "isPublic",
      "teams",
      "members",
      "contacts",
      "projects",
      "meetings",
      "notes",
      "tasks",
      "mysqlHost",
      "mysqlPort",
      "mysqlUser",
      "mysqlPassword",
      "mysqlDatabase",
      "mysqlTable",
      "mysqlConnectionType"
    ]);
    
    const workspace = await WorkspaceService.update(
      req.params.id,
      req.user._id,
      req.user.accountId,
      workspaceData
    );
    
    if (workspace) {
      return res.json(WorkspaceSerializer.show(workspace));
    } else {
      return res.status(422).json({
        success: false,
        message: "Failed to update workspace or workspace not found."
      });
    }
  }

  async delete(req, res) {
    const result = await WorkspaceService.delete(
      req.params.id,
      req.user._id,
      req.user.accountId
    );
    
    if (result) {
      return res.json({
        success: true,
        message: "Workspace deleted successfully."
      });
    } else {
      return res.status(404).json({
        success: false,
        message: "Workspace not found or you don't have permission to delete it."
      });
    }
  }

  async getWorkspaceFile(req, res) {
    // Existing implementation, unchanged
    try {
      const workspaceName = req.params.name;
      
      // Validate workspace name to prevent directory traversal
      if (!WorkspaceService.isValidWorkspaceFileName(workspaceName)) {
        return res.status(400).json({
          success: false,
          message: "Invalid workspace file name."
        });
      }
      
      const filePath = await WorkspaceService.getWorkspaceFilePath(workspaceName);
      
      // Check if the file exists
      const fileExists = await WorkspaceService.workspaceFileExists(filePath);
      
      if (!fileExists) {
        return res.status(404).json({
          success: false,
          message: "Workspace file not found."
        });
      }
      
      // Determine content type
      const contentType = WorkspaceService.getContentType(workspaceName);
      if (contentType) {
        res.set('Content-Type', contentType);
      }

      // Set filename for download
      res.set('Content-Disposition', `attachment; filename="${workspaceName}"`);
      
      // Send the file
      res.sendFile(filePath, (err) => {
        if (err) {
          console.error('Error sending file:', err);
          res.status(500).json({
            success: false,
            message: "Error sending workspace file."
          });
        }
      });
    } catch (error) {
      console.error('Error retrieving workspace file:', error);
      res.status(500).json({
        success: false,
        message: "Failed to retrieve workspace file."
      });
    }
  }

  // The database methods remain unchanged
  async getTableData(req, res) {
    try {
      const workspaceId = req.params.id;
      const limit = req.query.limit ? parseInt(req.query.limit) : 100;
      
      // Get the table data from the service
      const result = await WorkspaceService.getTableData(
        workspaceId,
        req.user._id,
        req.user.accountId,
        limit
      );
      
      return res.json({
        success: true,
        data: result
      });
    } catch (error) {
      console.error('Error fetching table data:', error);
      return res.status(500).json({
        success: false,
        message: error.message || "Failed to retrieve table data."
      });
    }
  }
  
  async listTables(req, res) {
    try {
      const workspaceId = req.params.id;
      
      // Get list of tables from the service
      const tables = await WorkspaceService.listTables(
        workspaceId,
        req.user._id,
        req.user.accountId
      );
      
      return res.json({
        success: true,
        tables: tables
      });
    } catch (error) {
      console.error('Error listing tables:', error);
      return res.status(500).json({
        success: false,
        message: error.message || "Failed to list database tables."
      });
    }
  }
  
  async testConnection(req, res) {
    try {
      const workspaceId = req.params.id;
      
      // Test the database connection
      const result = await WorkspaceService.testDatabaseConnection(
        workspaceId,
        req.user._id,
        req.user.accountId
      );
      
      return res.json({
        success: true,
        message: "Database connection successful",
        details: result
      });
    } catch (error) {
      console.error('Error testing database connection:', error);
      return res.status(500).json({
        success: false,
        message: error.message || "Failed to connect to database."
      });
    }
  }
}

export default new Controller();